﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Buccaneer;
using Buccontrols;

namespace PluginInterface
{
    public delegate void ActionFunction(string[] args);

    public enum ActionResult { success, argumentError, exception }

    public class PluginAction
    {
        public String name;
        public String friendlyName;
        public ActionFunction func;
        public Dictionary<string, string> pars = new Dictionary<string, string>();
        public Dictionary<string, ActionFunction> exceptions = new Dictionary<string, ActionFunction>();
        public PluginDaddy pluginDaddy;
        public PluginForm pluginForm;
        public IPlugin plugin;

        public ActionResult Execute(string[] args)
        {
            if ((pars.Count != 0 && (args == null || args[0] == "")) && NotOnlyOptionalPars())
            {
                this.Help();
                return ActionResult.argumentError;
            }

            try
            {
                try
                {
                    func.Invoke(args);
                }
                catch
                {
                    if (this.plugin != null && this.plugin.MainInterface != null && this.plugin.MainInterface.InvokeRequired)
                    {
                        Options.WriteComment("(i) Invoke required!");
                        this.plugin.MainInterface.Invoke(func, new object[] { args });
                    }
                    else if (this.plugin != null && this.plugin.Daddy != null && this.plugin.MainInterface.InvokeRequired)
                    {
                        Options.WriteComment("(i) Invoke required!");
                        this.plugin.Daddy.Invoke(func, new object[] { args });
                    }
                    else if (this.pluginForm != null && this.pluginForm.InvokeRequired)
                    {
                        Options.WriteComment("(i) Invoke required!");
                        this.pluginForm.Invoke(func, new object[] { args });
                    }
                    else if (this.pluginDaddy != null && this.pluginDaddy.InvokeRequired)
                    {
                        Options.WriteComment("(i) Invoke required!");
                        this.pluginDaddy.Invoke(func, new object[] { args });
                    }
                    else
                    {
                        func.Invoke(args);
                    }
                }
            }
            catch (InvalidOperationException)
            {
                if (this.pluginDaddy != null)
                {
                    Options.WriteComment("(i) Requesting to pluginDaddy");
                    this.pluginDaddy.ActRequest(name, args);
                }
                else if (this.plugin != null)
                {
                    Options.WriteComment("(i) Requesting to plugins Daddy");
                    plugin.Daddy.ActRequest(name, args);
                }
                else if (this.pluginForm != null)
                {
                    Options.WriteComment("(i) Requesting to pluginForm");
                    (this.pluginForm.Daddy as PluginDaddy).ActRequest(name, args);
                }
                else
                {
                    Options.WriteComment("(x) Failed!");
                }
            }
            catch (Exception ex)
            {
                try
                {
                    Type extype = ex.GetType();
                    string exstr = ex.GetType().ToString();
                    exceptions[exstr].Invoke(args);
                }
                catch (KeyNotFoundException)
                {
                    Options.WriteComment("(x) Uncought exception thrown: " + ex.Message);
                }
                catch (Exception ex2)
                {
                    Options.WriteComment("(x) Error in catching exception: " + ex2.Message);
                }
                return ActionResult.exception;
            }

            return ActionResult.success;
        }

        public void Help()
        {
            Options.WriteComment("(i) Information about function " + this.name + "([" + pars.Count + " parameters])");
            foreach (string key in pars.Keys)
            {
                Options.WriteComment((pars[key].StartsWith("optional:") || pars[key].StartsWith("opt:") ? " +  " : " -  ") + key + ": " + pars[key]);
            }
        }

        public static string ResultToString(ActionResult result)
        {
            switch (result)
            {
                case ActionResult.success:
                    return "The action succeeded!";
                case ActionResult.argumentError:
                    return "There was an error with the arguments!";
                case ActionResult.exception:
                    return "An exception was thrown";
                default:
                    return "An unknown error occurred";
            }
        }

        public bool NotOnlyOptionalPars()
        {
            if (pars.Count == 0) return false;
            foreach (string key in pars.Keys)
            {
                if (pars[key].StartsWith("optional:") || pars[key].StartsWith("opt:"))
                {
                    return false;
                }
            }

            return true;
        }
    }
}
